{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "SB93Ge748VQs"
      },
      "source": [
        "##### Copyright 2019 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "cellView": "form",
        "id": "0sK8X2O9bTlz"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HEYuO5NFwDK9"
      },
      "source": [
        "# TensorBoard を使う\n",
        "\n",
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td><a target=\"_blank\" href=\"https://www.tensorflow.org/tensorboard/get_started\"><img src=\"https://www.tensorflow.org/images/tf_logo_32px.png\">TensorFlow.org で表示</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs-l10n/blob/master/site/ja/tensorboard/get_started.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\">Google Colab を実行</a></td>\n",
        "  <td><a target=\"_blank\" href=\"https://github.com/tensorflow/docs-l10n/blob/master/site/ja/tensorboard/get_started.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\">GitHub でソースを表示</a></td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "56V5oun18ZdZ"
      },
      "source": [
        "機械学習では、何かを改善するには、それを測定できる必要があります。TensorBoard は機械学習ワークフローの際に必要な測定値と視覚化を提供するツールです。損失や精度などの実験メトリックのトラッキング、モデルグラフの視覚化、低次元空間への埋め込みの投影など、さまざまなことを行えます。\n",
        "\n",
        "このクイックスタートでは、TensorBoard を素早く使用し始める方法を示します。このウェブサイトの他のガイドでは、ここには含まれていない具体的な機能について、より詳しく説明します。 "
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "6B95Hb6YVgPZ"
      },
      "outputs": [],
      "source": [
        "# Load the TensorBoard notebook extension\n",
        "%load_ext tensorboard"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "_wqSAZExy6xV"
      },
      "outputs": [],
      "source": [
        "import tensorflow as tf\n",
        "import datetime"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Ao7fJW1Pyiza"
      },
      "outputs": [],
      "source": [
        "# Clear any logs from previous runs\n",
        "!rm -rf ./logs/ "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "z5pr9vuHVgXY"
      },
      "source": [
        "[MNIST](https://en.wikipedia.org/wiki/MNIST_database) データセットを例として使用しながら、データを正規化し、画像を 10 個のクラスに分類する単純な Keras モデルを作成する関数を記述します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "j-DHsby18cot"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz\n",
            "11493376/11490434 [==============================] - 0s 0us/step\n"
          ]
        }
      ],
      "source": [
        "mnist = tf.keras.datasets.mnist\n",
        "\n",
        "(x_train, y_train),(x_test, y_test) = mnist.load_data()\n",
        "x_train, x_test = x_train / 255.0, x_test / 255.0\n",
        "\n",
        "def create_model():\n",
        "  return tf.keras.models.Sequential([\n",
        "    tf.keras.layers.Flatten(input_shape=(28, 28)),\n",
        "    tf.keras.layers.Dense(512, activation='relu'),\n",
        "    tf.keras.layers.Dropout(0.2),\n",
        "    tf.keras.layers.Dense(10, activation='softmax')\n",
        "  ])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "XKUjdIoV87um"
      },
      "source": [
        "## Keras Model.fit() で TensorBoard を使用する"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "8CL_lxdn8-Sv"
      },
      "source": [
        "Keras の [Model.fit()](https://www.tensorflow.org/api_docs/python/tf/keras/models/Model#fit) を使用すると、`tf.keras.callbacks.TensorBoard` コールバックによってログが作成され、保存されたこと保証できます。さらに、`histogram_freq=1`（デフォルトでは無効）でエポックごとにヒストグラム計算を行えます。\n",
        "\n",
        "トレーニング実行を簡単に選択できるように、ログをタイムスタンプ付きのサブディレクトリに配置しましょう。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "WAQThq539CEJ"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Train on 60000 samples, validate on 10000 samples\n",
            "Epoch 1/5\n",
            "60000/60000 [==============================] - 15s 246us/sample - loss: 0.2217 - accuracy: 0.9343 - val_loss: 0.1019 - val_accuracy: 0.9685\n",
            "Epoch 2/5\n",
            "60000/60000 [==============================] - 14s 229us/sample - loss: 0.0975 - accuracy: 0.9698 - val_loss: 0.0787 - val_accuracy: 0.9758\n",
            "Epoch 3/5\n",
            "60000/60000 [==============================] - 14s 231us/sample - loss: 0.0718 - accuracy: 0.9771 - val_loss: 0.0698 - val_accuracy: 0.9781\n",
            "Epoch 4/5\n",
            "60000/60000 [==============================] - 14s 227us/sample - loss: 0.0540 - accuracy: 0.9820 - val_loss: 0.0685 - val_accuracy: 0.9795\n",
            "Epoch 5/5\n",
            "60000/60000 [==============================] - 14s 228us/sample - loss: 0.0433 - accuracy: 0.9862 - val_loss: 0.0623 - val_accuracy: 0.9823\n"
          ]
        },
        {
          "data": {
            "text/plain": [
              "<tensorflow.python.keras.callbacks.History at 0x7fc8a5ee02e8>"
            ]
          },
          "execution_count": 6,
          "metadata": {
            "tags": []
          },
          "output_type": "execute_result"
        }
      ],
      "source": [
        "model = create_model()\n",
        "model.compile(optimizer='adam',\n",
        "              loss='sparse_categorical_crossentropy',\n",
        "              metrics=['accuracy'])\n",
        "\n",
        "log_dir = \"logs/fit/\" + datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\")\n",
        "tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=log_dir, histogram_freq=1)\n",
        "\n",
        "model.fit(x=x_train, \n",
        "          y=y_train, \n",
        "          epochs=5, \n",
        "          validation_data=(x_test, y_test), \n",
        "          callbacks=[tensorboard_callback])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "asjGpmD09dRl"
      },
      "source": [
        "コマンドラインから、またはノートブックエクスペリエンス内で TensorBoard を起動します。2 つのインターフェースはほぼ同じです。ノートブックでは、`%tensorboard` ラインマジックを使用しますが、コマンドラインでは同じコマンドを「%」をつけずに実行します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "A4UKgTLb9fKI"
      },
      "outputs": [],
      "source": [
        "%tensorboard --logdir logs/fit"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "MCsoUNb6YhGc"
      },
      "source": [
        " <img src=\"https://github.com/tensorflow/tensorboard/blob/master/docs/images/quickstart_model_fit.png?raw=1\" class=\"\"> "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Gi4PaRm39of2"
      },
      "source": [
        "ダッシュボード（トップナビゲーションバーのタブ）を簡単に説明します。\n",
        "\n",
        "- **Scalars** ダッシュボードには、エポックごとの損失とメトリックの変化が示されます。これを使用して、トレーニング速度、学習率、およびその他のスカラー値をトラッキングすることもできます。\n",
        "- **Graphs** ダッシュボードには、モデルが視覚化されます。このケースではレイヤーの Keras グラフが示されており、正しく構築されていることを確認しやすくなります。\n",
        "- **Distributions** と **Histograms** ダッシュボードには、経時的なテンソルの分布が示されます。重みとバイアスを視覚化し、期待する方法で変化していることを確認する上で役立ちます。\n",
        "\n",
        "ほかの種類のデータをログ記録すると、追加の TensorBoard プラグインが自動的に有効化されます。たとえば、Keras TensorBoard コールバックの場合は、画像と埋め込みもログ記録することができます。TensorBoard で利用できるほかのプラグインを確認するには、右上の方にある「inactive」ドロップダウンをクリックしてください。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "nB718NOH95yG"
      },
      "source": [
        "## ほかのメソッドで TensorBoard を使用する\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "IKNt0nWs-Ekt"
      },
      "source": [
        "[`tf.GradientTape()`](https://www.tensorflow.org/api_docs/python/tf/GradientTape) などのメソッドでトレーニングする場合に必要な情報をログ記録するには、`tf.summary` を使用します。\n",
        "\n",
        "上記と同じデータセットを使用しますが、`tf.data.Dataset` に変換して、バッチ機能を利用しましょう。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "nnHx4DsMezy1"
      },
      "outputs": [],
      "source": [
        "train_dataset = tf.data.Dataset.from_tensor_slices((x_train, y_train))\n",
        "test_dataset = tf.data.Dataset.from_tensor_slices((x_test, y_test))\n",
        "\n",
        "train_dataset = train_dataset.shuffle(60000).batch(64)\n",
        "test_dataset = test_dataset.batch(64)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "SzpmTmJafJ10"
      },
      "source": [
        "トレーニングコードは[高度なクイックスタート](https://www.tensorflow.org/tutorials/quickstart/advanced)チュートリアルの内容に従いますが、メトリックを TensorBoard にログ記録する方法が示されています。損失とオプティマイザを選択してください。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "H2Y5-aPbAANs"
      },
      "outputs": [],
      "source": [
        "loss_object = tf.keras.losses.SparseCategoricalCrossentropy()\n",
        "optimizer = tf.keras.optimizers.Adam()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "cKhIIDj9Hbfy"
      },
      "source": [
        "トレーニング中の値を蓄積するために使用し、任意の時点でログ記録できるステートフルメトリックを作成します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "jD0tEWrgH0TL"
      },
      "outputs": [],
      "source": [
        "# Define our metrics\n",
        "train_loss = tf.keras.metrics.Mean('train_loss', dtype=tf.float32)\n",
        "train_accuracy = tf.keras.metrics.SparseCategoricalAccuracy('train_accuracy')\n",
        "test_loss = tf.keras.metrics.Mean('test_loss', dtype=tf.float32)\n",
        "test_accuracy = tf.keras.metrics.SparseCategoricalAccuracy('test_accuracy')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "szw_KrgOg-OT"
      },
      "source": [
        "トレーニングとテストの関数を定義します。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "TTWcJO35IJgK"
      },
      "outputs": [],
      "source": [
        "def train_step(model, optimizer, x_train, y_train):\n",
        "  with tf.GradientTape() as tape:\n",
        "    predictions = model(x_train, training=True)\n",
        "    loss = loss_object(y_train, predictions)\n",
        "  grads = tape.gradient(loss, model.trainable_variables)\n",
        "  optimizer.apply_gradients(zip(grads, model.trainable_variables))\n",
        "\n",
        "  train_loss(loss)\n",
        "  train_accuracy(y_train, predictions)\n",
        "\n",
        "def test_step(model, x_test, y_test):\n",
        "  predictions = model(x_test)\n",
        "  loss = loss_object(y_test, predictions)\n",
        "\n",
        "  test_loss(loss)\n",
        "  test_accuracy(y_test, predictions)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "nucPZBKPJR3A"
      },
      "source": [
        "logs ディレクトリに要約をディスクに書き込むためのサマリーライターをセットアップします。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "3Qp-exmbWf4w"
      },
      "outputs": [],
      "source": [
        "current_time = datetime.datetime.now().strftime(\"%Y%m%d-%H%M%S\")\n",
        "train_log_dir = 'logs/gradient_tape/' + current_time + '/train'\n",
        "test_log_dir = 'logs/gradient_tape/' + current_time + '/test'\n",
        "train_summary_writer = tf.summary.create_file_writer(train_log_dir)\n",
        "test_summary_writer = tf.summary.create_file_writer(test_log_dir)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qgUJgDdKWUKF"
      },
      "source": [
        "トレーニングを開始します。サマリーライターがディスクに要約を書き込めるように、`tf.summary.scalar()` を使用して、トレーニング/テスト中のメトリック（損失と精度）をログします。ログするメトリックとその頻度は、ユーザーが制御します。ほかの `tf.summary` 関数は、ほかの種類のデータのログに使用されます。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "odWvHPpKJvb_"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Epoch 1, Loss: 0.24321186542510986, Accuracy: 92.84333801269531, Test Loss: 0.13006582856178284, Test Accuracy: 95.9000015258789\n",
            "Epoch 2, Loss: 0.10446818172931671, Accuracy: 96.84833526611328, Test Loss: 0.08867532759904861, Test Accuracy: 97.1199951171875\n",
            "Epoch 3, Loss: 0.07096975296735764, Accuracy: 97.80166625976562, Test Loss: 0.07875105738639832, Test Accuracy: 97.48999786376953\n",
            "Epoch 4, Loss: 0.05380449816584587, Accuracy: 98.34166717529297, Test Loss: 0.07712937891483307, Test Accuracy: 97.56999969482422\n",
            "Epoch 5, Loss: 0.041443776339292526, Accuracy: 98.71833038330078, Test Loss: 0.07514958828687668, Test Accuracy: 97.5\n"
          ]
        }
      ],
      "source": [
        "model = create_model() # reset our model\n",
        "\n",
        "EPOCHS = 5\n",
        "\n",
        "for epoch in range(EPOCHS):\n",
        "  for (x_train, y_train) in train_dataset:\n",
        "    train_step(model, optimizer, x_train, y_train)\n",
        "  with train_summary_writer.as_default():\n",
        "    tf.summary.scalar('loss', train_loss.result(), step=epoch)\n",
        "    tf.summary.scalar('accuracy', train_accuracy.result(), step=epoch)\n",
        "\n",
        "  for (x_test, y_test) in test_dataset:\n",
        "    test_step(model, x_test, y_test)\n",
        "  with test_summary_writer.as_default():\n",
        "    tf.summary.scalar('loss', test_loss.result(), step=epoch)\n",
        "    tf.summary.scalar('accuracy', test_accuracy.result(), step=epoch)\n",
        "  \n",
        "  template = 'Epoch {}, Loss: {}, Accuracy: {}, Test Loss: {}, Test Accuracy: {}'\n",
        "  print (template.format(epoch+1,\n",
        "                         train_loss.result(), \n",
        "                         train_accuracy.result()*100,\n",
        "                         test_loss.result(), \n",
        "                         test_accuracy.result()*100))\n",
        "\n",
        "  # Reset metrics every epoch\n",
        "  train_loss.reset_states()\n",
        "  test_loss.reset_states()\n",
        "  train_accuracy.reset_states()\n",
        "  test_accuracy.reset_states()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "JikosQ84fzcA"
      },
      "source": [
        "TensorBoard をもう一度開き、新しいログディレクトリにポイントします。また、TensorBoard を起動してトレーニングの経過を監視することもできます。"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "-Iue509kgOyE"
      },
      "outputs": [],
      "source": [
        "%tensorboard --logdir logs/gradient_tape"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "NVpnilhEgQXk"
      },
      "source": [
        " <img src=\"https://github.com/tensorflow/tensorboard/blob/master/docs/images/quickstart_gradient_tape.png?raw=1\" class=\"\"> "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ozbwXgPIkCKV"
      },
      "source": [
        "これで完了です！Keras コールバックと、ほかのカスタムシナリオで使用できる `tf.summary` を使って TensorBoardを使用する方法を確認しました。 "
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vsowjhkBdkbK"
      },
      "source": [
        "## TensorBoard.dev: ML 実験結果のホストと共有\n",
        "\n",
        "[TensorBoard.dev](https://tensorboard.dev) は無料の一般公開サービスで、TensorBoard ログをアップロードし、学術論文、ブログ投稿、ソーシャルメディアなどでの共有に使用するパーマリンクを取得することができます。このサービスにより、再現性と共同作業をさらに改善することができます。\n",
        "\n",
        "TensorBoard.dev を使用するには、次のコマンドを実行してください。\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Q3nupQL24E5E"
      },
      "outputs": [],
      "source": [
        "!tensorboard dev upload \\\n",
        "  --logdir logs/fit \\\n",
        "  --name \"(optional) My latest experiment\" \\\n",
        "  --description \"(optional) Simple comparison of several hyperparameters\" \\\n",
        "  --one_shot"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "lAgEh_Ow4EX6"
      },
      "source": [
        "この呼び出しでは、パーセント記号（`%`）のプレフィクスを使って Colab マジックを呼び出すのではなく、感嘆符（`!`）をプレフィクスとしてシェルを呼び出していることに注意してください。コマンドラインからこのコマンドを呼び出す際は、いずれのプレフィクスも必要ありません。\n",
        "\n",
        "[こちら](https://tensorboard.dev/experiment/EDZb7XgKSBKo6Gznh3i8hg/#scalars)で例をご覧ください。\n",
        "\n",
        "TensorBoard.dev の詳しい使用方法については、https://tensorboard.dev/#get-started をご覧ください。"
      ]
    }
  ],
  "metadata": {
    "colab": {
      "collapsed_sections": [],
      "name": "get_started.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
